package top.mindse.oss;


import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PolicyConditions;
import lombok.extern.slf4j.Slf4j;
import top.mindse.model.OssPolicy;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;

/**
 * aliyun-oss 上传逻辑类
 *
 * @author mindse
 */
@Slf4j
public class AliyunStorage implements Storage {

    private static final String SEPARATOR = "/";

    private final OSSClient ossClient;

    public AliyunStorage(OSSClient ossClient) {
        this.ossClient = ossClient;
    }

    @Override
    public void uploadFile(String bucketName, String storagePath, String fileName, InputStream inputStream, String contentType) {
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType(contentType);
        this.ossClient.putObject(bucketName, getKey(storagePath, fileName), inputStream, objectMetadata);
    }

    @Override
    public InputStream getFile(String bucketName, String storagePath, String fileName) {
        return this.ossClient.getObject(bucketName, getKey(storagePath, fileName)).getObjectContent();
    }

    @Override
    public String getFileUrl(String bucketName, String storagePath, String fileName) {
        return "https://" + bucketName + "." + this.ossClient.getEndpoint().getHost() + "/" + getKey(storagePath, fileName);
    }

    @Override
    public void removeFile(String bucketName, String storagePath, String fileName) {
        this.ossClient.deleteObject(bucketName, getKey(storagePath, fileName));
    }

    @Override
    public OssPolicy getOssPolicy(String bucketName, String storagePath, int maxSize, int policeExpire) {
        OssPolicy ossPolicy = new OssPolicy();
        // 签名有效期
        long expireEndTime = System.currentTimeMillis() + policeExpire * 1000;
        Date expiration = new Date(expireEndTime);
        // 文件大小
        long maxFileSize = maxSize * 1024 * 1024;
        // 提交节点
        String action = "https://" + bucketName + "." + ossClient.getEndpoint().getHost();

        String key = getStoragePath(storagePath);
        try {
            PolicyConditions policyConditions = new PolicyConditions();
            policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxFileSize);
            policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, getStoragePath(storagePath));
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConditions);
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String policy = BinaryUtil.toBase64String(binaryData);
            String signature = ossClient.calculatePostSignature(postPolicy);
            // 返回结果
            ossPolicy.setOssaccessKeyId(ossClient.getCredentialsProvider().getCredentials().getAccessKeyId());
            ossPolicy.setPolicy(policy);
            ossPolicy.setSignature(signature);
            ossPolicy.setKey(key);
            ossPolicy.setHost(action);
            ossPolicy.setUrl(action + SEPARATOR + key);
            ossPolicy.setSuccess_action_status(200);
        } catch (Exception e) {
            log.error("签名生成失败", e);
        }
        return ossPolicy;
    }

    /**
     * 文件存储路径
     *
     * @param storagePath 存储路径
     * @param fileName    文件名称
     * @return String
     */
    private String getKey(String storagePath, String fileName) {
        if (storagePath == null || "".equals(storagePath)) {
            return fileName;
        }
        return getStoragePath(storagePath) + fileName;
    }

    /**
     * 文件存储目录
     *
     * @param storagePath 存储路径
     * @return String
     */
    private String getStoragePath(String storagePath) {
        if (storagePath.endsWith(SEPARATOR)) {
            return storagePath;
        } else {
            return storagePath + SEPARATOR;
        }

    }
}
